package com.boot.utils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @author Chunsheng.Zhang
 * @date 2021/3/30 16:06
 * @description : TODO
 */
public class SignatureGenerateUtil {


    /**
     * @description: 获取签名信息
     * @author: ChunSheng.Zhang
     * @date: 2021/3/30 16:11
     * @param paramBody  排除了值为null的json字符串    ba=3&cd=4&af=5&ff=22&ea=xx
     * @return java.lang.String
     **/
    public static String generate(String paramBody,String secretKey){
        paramBody = paramBody.toUpperCase();
        System.out.println("转成小写后：*********" + paramBody);

        //1.取出paramBody中所有的参数，并根据首字母按param1=value1&param2=value2排序拼接得到sortParam
        String sortParam = SignUtil.getOrderedParamsString(paramBody);

        //2.拼接SecretKey，得到stringSignTemp
        String stringSignTemp = sortParam + "&secretKey=" + secretKey;


        //3.将stringSignTemp进行md5加密，从而得到签名sign
        String sign = MD5Helper.md5Sign(stringSignTemp);


        return sign;
    }




    /**
     * @description: 签名验证
     * @author: ChunSheng.Zhang
     * @date: 2021/3/30 17:28
     * @param paramBody 请求参数 accessKey=oa&userName=zcs&passWord=xfsaf
     * @param secretKey 客户唯一标识
     * @param reqSign 客户侧获取的签名
     * @return boolean
     **/
    public static boolean verifySign (String paramBody,String secretKey,String reqSign){

        String sign = generate(paramBody, secretKey);

        if(StringUtil.isBlank(reqSign)){
            return false;
        }
        if(reqSign.equals(sign)){
            return true;
        }

        return false;
    }




    //md5静态内部类
    public static class MD5Helper{
        private static final char[] DIGITS = new char[] {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f' };

        public static String md5Sign(String text) {
            MessageDigest msgDigest = null;
            try {
                msgDigest = MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException e) {
                throw new IllegalStateException();
            }
            try {
                msgDigest.update(text.getBytes("UTF-8"));
            } catch (UnsupportedEncodingException e) {
                throw new IllegalStateException();
            }
            byte[] bytes = msgDigest.digest();
            return encodeHex(bytes);
        }

        public static String encodeHex(byte[] data) {
            int l = data.length;
            char[] out = new char[l << 1];
            for (int i = 0, j = 0; i < l; i++) {
                out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
                out[j++] = DIGITS[0xF & data[i]];
            }
            return new String(out);
        }
    }


    //签名静态内部
    public static class SignUtil{
        public static String getOrderedParamsString(String paramsString) {
            if (StringUtil.isBlank(paramsString)){
                return null;
            }

            String orderedString = null;
            String[] paramsArray = paramsString.split("&");
            if (paramsArray.length == 1) {
                orderedString = paramsArray[0];
            } else {
                List<String> paramsList = Arrays.asList(paramsArray);
                Collections.sort(paramsList);
                StringBuilder sb = new StringBuilder();
                for (String param : paramsList) {
                    if (!StringUtil.isBlank(param)){
                        sb.append(param).append("&");
                    }
                }
                sb.deleteCharAt(sb.length() - 1);
                orderedString = sb.toString();
            }
            return orderedString;
        }



        public static String getOrderedParamsString(Map<String, String[]> paramsMap) {
            if (paramsMap == null || paramsMap.size() == 0){
                return null;
            }
            StringBuilder requestString = new StringBuilder();
            if (paramsMap != null && paramsMap.size() > 0) {
                Map<String, String> sortParamsMap = new TreeMap<>();
                String[] valueArray = null;
                Set<Map.Entry<String, String[]>> entrySet = (Set)paramsMap.entrySet();
                for (Map.Entry<String, String[]> entry : entrySet) {
                    valueArray = entry.getValue();
                    if (valueArray == null || valueArray.length == 0) {
                        sortParamsMap.put(entry.getKey(), "");
                        continue;
                    }
                    if (valueArray.length == 1) {
                        sortParamsMap.put(entry.getKey(), valueArray[0]);
                        continue;
                    }
                    List<String> valueList = Arrays.asList(valueArray);
                    Collections.sort(valueList);
                    sortParamsMap.put(entry.getKey(), valueList.toString());
                }
                Set<Map.Entry<String, String>> sortEntrySet = sortParamsMap.entrySet();
                for (Map.Entry<String, String> sortEntry : sortEntrySet){
                    requestString.append(sortEntry.getKey()).append("=").append(sortEntry.getValue()).append("&");
                }
                requestString.deleteCharAt(requestString.length() - 1);
            }
            return requestString.toString();
        }
    }



    //字符串工具类静态内部类
    public static class StringUtil{
        public static boolean isBlank(String string) {
            return (string == null || string.trim().length() == 0);
        }


        public static String randomStr(){
            return UUID.randomUUID().toString();
        }

    }


}








